﻿//1、公有，私有，保护

//公有：在类内和内外可以随便访问
//私有：在类内可以随便访问，在类外不可以访问，可以在类中写一个get函数取访问私有成员
//保护：在类内可以随便访问，在类外只允许子类成员对象访问

#include <iostream>
using namespace std;

class Base {
public:
    int a = 10;  // 公有成员
protected:
    int b = 20;  // 保护成员
private:
    int c = 30;  // 私有成员
};

class Derived : public Base {
public:
    void show() {
        cout << "a = " << a << endl;  // ✅ 可以访问
        cout << "b = " << b << endl;  // ✅ 可以访问
        // cout << "c = " << c << endl;  // ❌ 编译错误：派生类不能访问 private 成员
    }
};

int main() {
    Derived d;
    cout << d.a << endl;  // ✅ 允许访问
    // cout << d.b << endl;  // ❌ 编译错误：protected 成员不可在外部访问
    // cout << d.c << endl;  // ❌ 编译错误：private 成员不可在外部访问
    d.show();
    return 0;
}



class Base {
public:
    int a = 10;
protected:
    int b = 20;
private:
    int c = 30;
};

class Derived1 : public Base {};   // 公有继承
class Derived2 : protected Base {}; // 保护继承
class Derived3 : private Base {};   // 私有继承

int main() {
    Derived1 d1;
    cout << d1.a << endl; // ✅ 允许访问（public 继承后仍然是 public）
    // cout << d1.b << endl; // ❌ 不能访问（protected 成员外部不可访问）
    // cout << d1.c << endl; // ❌ 不能访问（private 成员不可访问）

    Derived2 d2;
    // cout << d2.a << endl; // ❌ 不能访问（protected 继承后，public 成员变成 protected）
    // cout << d2.b << endl; // ❌ 不能访问（protected 成员外部不可访问）

    Derived3 d3;
    // cout << d3.a << endl; // ❌ 不能访问（private 继承后，public 成员变成 private）
}



//2、类中公有成员int a,和static int b 的区别
                   
//存储位置：  堆区或栈区（每个对象都有一份）    全局区（全局只有一份）     
//作用范围：  当前对象                          作用与整个类，所有对象共享
//生命周期：  跟随对象的生命周期                全局
//访问方式：  对象访问                          对象和类名都可
//初始化方式：构造函数中初始化                  类外初始化
//共享性：    仅仅影响当前对象                  影响所有对象


//3、构造函数前面加explicitd的作用是什么
//explicit	防止隐式类型转换
//使用场景	单参数构造函数，避免 A a = 10; 形式的隐式转换
//多参数构造函数	只有当第二个参数有默认值时，explicit 仍然生效
//STL explicit	防止 vector<int> v = 10; 这样的代码
//C++11 转换运算符	explicit operator bool() 防止 if (obj) 这样的隐式转换



//4、智能指针怎么实现一个自己的销毁指针的方式（传参，函数指针->仿函数和lambda）
//1、自定义删除器（lambda）
//2、仿函数
//3、函数指针

#include <iostream>
#include <functional>  // std::function

using namespace std;

template <typename T>
class MyUniquePtr {
private:
    T* ptr;
    function<void(T*)> deleter;  // 允许自定义删除方式

public:
    // 构造函数
    MyUniquePtr(T* p, function<void(T*)> del = [](T* p) { delete p; })
        : ptr(p), deleter(del) {}

    // 禁止拷贝
    MyUniquePtr(const MyUniquePtr&) = delete;
    MyUniquePtr& operator=(const MyUniquePtr&) = delete;

    // 允许移动
    MyUniquePtr(MyUniquePtr&& other) noexcept : ptr(other.ptr), deleter(move(other.deleter)) {
        other.ptr = nullptr;
    }

    MyUniquePtr& operator=(MyUniquePtr&& other) noexcept {
        if (this != &other) {
            reset();
            ptr = other.ptr;
            deleter = move(other.deleter);
            other.ptr = nullptr;
        }
        return *this;
    }

    // 获取指针
    T* get() const { return ptr; }

    // 释放资源
    void reset() {
        if (ptr) {
            deleter(ptr);
            ptr = nullptr;
        }
    }

    // 重载 `->` 和 `*`
    T* operator->() { return ptr; }
    T& operator*() { return *ptr; }

    // 析构函数
    ~MyUniquePtr() { reset(); }
};

int main() {
    // 自定义删除器
    auto customDeleter = [](int* p) {
        cout << "Custom delete for: " << *p << endl;
        delete p;
    };

    MyUniquePtr<int> ptr(new int(50), customDeleter);

    cout << "Value: " << *ptr << endl;

    return 0; // `ptr` 离开作用域时调用 customDeleter
}



//5、time_wait状态
//谁主动断开连接就处于time_wait(等待超时)状态 ------------ 完成四次挥手后等待一段时间（默认是2MSL）后在彻底释放端口状态


//为什么需要time_wait状态
//1、防止就的数据包影响新的连接
// TCP 是可靠传输协议，如果立即关闭连接，网络上可能还残留旧的 TCP 数据包，可能会影响新连接。
//2、确保被动关闭方正确关闭
// 如果 A 发送的最后一个 ACK 丢失，B 没有收到，B 仍然认为连接存在：
//                                                 B 会重新发送 FIN 请求关闭连接。
//                                                 如果 A 直接关闭，B 收不到 ACK，可能进入错误状态。
//                                                 TIME_WAIT 确保 A 仍然可用，并能正确地接收和处理 B 可能的 FIN 重传。



如果短时间内有大量 TCP 连接进入 TIME_WAIT，可能会导致：

端口耗尽（大量端口被占用）。
服务器无法建立新连接（连接数过多，影响业务）。

netstat - an | grep TIME_WAIT | wc - l  //查看time_wait连接数


TIME_WAIT 触发条件	主动关闭 TCP 连接的一方 会进入 TIME_WAIT
TIME_WAIT 作用	1. 防止旧数据包干扰新连接；2.确保对方收到 FIN 并能正确关闭
TIME_WAIT 超时	默认 2 * MSL（约 60s），防止旧数据包影响新连接
TIME_WAIT 多导致的问题	服务器端口耗尽、连接数爆满
优化方法	1. 开启端口重用（tcp_tw_reuse）；2.调整超时时间；3.让服务器被动关闭


//6、什么情况会出现大量的time_wait状态
服务器主动关闭连接	让客户端主动关闭，使用长连接
短连接（HTTP 1.0 / RPC）	使用 HTTP 1.1 Keep - Alive / 连接池
负载均衡 / 代理（Nginx）主动关闭连接	启用 HTTP 1.1 + Keep - Alive
NAT / 端口复用问题	关闭 tcp_tw_recycle，启用 tcp_tw_reuse
端口耗尽	增大端口范围 ip_local_port_range，降低 tcp_fin_timeout


7、
#include <iostream>

int& getStaticObject() {
    int a = 100;
    int& staticVar = a;  // 静态局部变量
    return staticVar;            // 返回静态变量的引用
}

int main() {
    int& ref = getStaticObject();  // 获取静态变量的引用
    std::cout << ref << std::endl; // 输出 100
    return 0;
}
错误原因：
在 getStaticObject() 函数中，你声明了一个局部变量 a，然后让 staticVar 引用它：int& staticVar = a; 
这个局部变量 a 的生命周期仅限于 getStaticObject() 函数的作用域。当 getStaticObject() 函数返回后，a 会被销毁，
导致 staticVar 成为一个悬空引用（即引用一个已经被销毁的对象）。
因此，返回 staticVar 时会导致 未定义行为，因为它引用了一个已经销毁的局部变量。

解决办法：
1、使用 静态局部变量 来延长对象的生命周期。静态局部变量的生命周期贯穿整个程序运行周期，直到程序结束时才会被销毁。

2、如果你需要返回的对象是在函数外部使用的，可以使用 动态内存分配（例如 new）来分配堆上的内存。
   动态分配的对象的生命周期会一直持续到你显式调用 delete 释放它。

3、你可以将对象创建在函数外部，或者将对象作为参数传入函数，这样它的生命周期由外部代码管理，避免了局部对象生命周期结束的问题。

4、使用 std::move 和返回局部对象（适用于临时对象）
   C++11 引入了 std::move，它允许我们将对象的所有权从一个变量转移到另一个变量，从而避免复制开销。如果我们不再需要原始对象，
   可以使用 std::move 将对象转移给函数的返回值。

5、使用智能指针：std::unique_ptr 和 std::shared_ptr 可以有效管理对象的生命周期，避免悬空引用。




